﻿using System;
using System.Json;
using System.Xml.Linq;
using System.Xml;
using System.ServiceModel.Syndication;
using MichMan.Utilities;
using MichMan.Utilities.Requests;
using System.Collections.Generic;

namespace MichMan.Utilities.UnitTest
{
    public class CatalogItem : AtomEntry
    {
        [ZPath("sortTitle")]
        public string SortTitle { get; set; }

        [ZPath("id")]
        public Guid GuidId { get; set; }
    }

    public class TrackDetailsRequest : AtomEntryRequest<CatalogItem>
    {
        public TrackDetailsRequest()
        {
            Uri = new Uri(@"http://catalog.zune.net/v3.0/music/track/d5d93200-0100-11db-89ca-0019b92a3933");
        }
    }

    public class CatalogDataRequest : DataRequest<string>
    {
        public CatalogDataRequest()
        {
            Uri = new Uri(@"http://catalog.zune.net/v3.0/music/track/d5d93200-0100-11db-89ca-0019b92a3933");
        }
    }

    public class YahooImageRequest : DataRequest<JsonObject>
    {
        public YahooImageRequest()
        {
            Uri = new Uri(@"http://search.yahooapis.com/ImageSearchService/V1/imageSearch?appid=YahooDemo&query=Madonna&output=json");
        }
    }

    public class CompoundCatalogRequest : DataRequest<XElement>
    {
        public override void RunRequestAsync()
        {
            RequestStatus = RequestStatus.Started;

            DataRequest<XElement> albumSearch = new DataRequest<XElement>();
            albumSearch.Uri = new Uri(@"http://catalog.zune.net/v3.0/music/album?q=Thriller");
            albumSearch.RunRequestCompleted += (s, e) =>
                {
                    if (albumSearch.Error != null)
                    {
                        Error = albumSearch.Error;
                        return;
                    }

                    DataRequest<XElement> albumDetail = new DataRequest<XElement>();
                    string id = albumSearch.Response.GetZPathValue("entry[1]/id").Replace("urn:uuid:", "");
                    if (String.IsNullOrEmpty(id))
                    {
                        Error = new Exception("Bad feed format.");
                    }
                    albumDetail.Uri = new Uri(@"http://catalog.zune.net/v1.2/music/album/" + id);
                    albumDetail.RunRequestCompleted += (s1, e1) =>
                        {
                            if (albumSearch.Error != null)
                            {
                                Error = albumSearch.Error;
                                return;
                            }
                           
                            Response = albumDetail.Response;
                        };
                    albumDetail.RunRequestAsync();
                };
            albumSearch.RunRequestAsync();
        }
    }

    public class RetryRequest : DataRequest<XElement>
    {
        public override void RunRequestAsync()
        {

            Uri = new Uri(@"http://catalog.zune.net/v3.0/music/ThisIsNotAlbum?q=Thriller");
            base.RunRequestAsync();
        }

        private bool Retry { get; set; }

        protected override void OnRunRequestCompleted(RunRequestCompletedEventArgs runRequestCompletedEventArgs)
        {
            // I may have set the wrong url.
            if (Retry == false && Error != null)
            {
                Retry = true;

                // Ooops.  Wrong Url.  Retry.
                Uri = new Uri(@"http://catalog.zune.net/v3.0/music/album?q=Thriller");
                RunRequestAsyncInternal();
            }
            else
            {
                base.OnRunRequestCompleted(runRequestCompletedEventArgs);
            }
        }
    }

    /// <summary>
    /// Support a type not supported natively by SimpleDataRequest.
    /// </summary>
    public class CustomDataRequest : DataRequest<XDocument>
    {
        public CustomDataRequest()
        {
            Uri = new Uri(@"http://catalog.zune.net/v3.0/music/album?q=Thriller");
            // Uri = new Uri(@"http://services.digg.com/1.0/endpoint?method=search.stories&query=GaGa");
        }

        protected override void ProcessResult(XmlReader reader)
        {
            Response = XDocument.Load(reader);
        }
    }

    /// <summary>
    /// Fail to support a type not supported natively by SimpleDataRequest.
    /// </summary>
    public class UnsupportedCustomDataRequest : DataRequest<SyndicationFeed>
    {
        public UnsupportedCustomDataRequest()
        {
            Uri = new Uri(@"http://catalog.zune.net/v3.0/music/album?q=Monster");
        }

        /* 
        // This code would make it a supported type.
        protected override void ProcessResult(XmlReader reader)
        {
            Response = SyndicationFeed.Load(reader);
        }
        */
    }

    public class SyndicationRequest : DataRequest<SyndicationFeed>
    {
        // This code would make it a supported type.
        protected override void ProcessResult(XmlReader reader)
        {
            Response = SyndicationFeed.Load(reader);
        }
    }

    [UriFormat("http://catalog.zune.net/{ver}/{mediaType}/{itemType}")]
    public class CatalogRequest<T> : DataRequest<T>
        where T : class
    {
        public CatalogRequest()
        {
            Version = "v3.0";
        }

        [UriParam("ver")]
        public string Version { get; set; }

        [UriParam("mediaType")]
        public string MediaType { get; set; }

        [UriParam("itemType")]
        public string ItemType { get; set; }
    }

    public class CatalogSearchRequest<T> : CatalogRequest<T>
        where T : class
    {
        [QueryParam("q", Required=true)]
        public string Query { get; set; }
    }

    [UriFormat("http://catalog.zune.net/{ver}/music/album")]
    public class AlbumSearchRequest : AtomFeedRequest<CatalogItem>
    {
        public AlbumSearchRequest()
        {
            Version = "v3.0";
        }

        [UriParam("ver")]
        public string Version { get; set; }

        [QueryParam("q", Required = true)]
        public string Query { get; set; }
    }
}